﻿

/* 
 * Author: Mikkel Thordal Andersen, Juan Mompean Esteban
 * Created: 26.11.2011
 */
namespace ITU_vs_Zombies.Menu.Screens
{
    using System;
    using System.IO;
    using System.Runtime.Serialization.Formatters.Binary;

    using ITU_vs_Zombies.Character;
    using ITU_vs_Zombies.Game;
    using ITU_vs_Zombies.Graphics;
    using ITU_vs_Zombies.Movement;
    using ITU_vs_Zombies.Scenery;
    using ITU_vs_Zombies.Stuff;

    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Audio;
    using Microsoft.Xna.Framework.Content;
    using Microsoft.Xna.Framework.GamerServices;
    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;
    using Microsoft.Xna.Framework.Media;
    using Microsoft.Xna.Framework.Storage;

    internal class MainMenuScreen : MenuScreen
    {
        #region Constructors and Destructors

        public MainMenuScreen()
            : base("Main Menu")
        {
            // Create our menu entries.
            var playGameMenuEntry = new MenuEntry("Play Game");
            var loadGameMenuEntry = new MenuEntry("Load Game");
            var statisticsMenuEntry = new MenuEntry("Statistics");
            var identitiesMenuEntry = new MenuEntry("Profiles");
            var exitMenuEntry = new MenuEntry("Exit");

            // Hook up menu event handlers.
            playGameMenuEntry.Selected += this.PlayGameMenuEntrySelected;
            loadGameMenuEntry.Selected += this.LoadGameMenuEntrySelected;
            statisticsMenuEntry.Selected += this.StatisticsMenuEntrySelected;
            identitiesMenuEntry.Selected += this.IdentitiesMenuEntrySelected;
            exitMenuEntry.Selected += OnCancel;

            // Add entries to the menu.
            this.MenuEntries.Add(playGameMenuEntry);
            this.MenuEntries.Add(loadGameMenuEntry);
            this.MenuEntries.Add(statisticsMenuEntry);
            this.MenuEntries.Add(identitiesMenuEntry);
            this.MenuEntries.Add(exitMenuEntry);
            this.SongName = @"Sounds\MenuSound";
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// The activate.
        /// </summary>
        /// <param name="instancePreserved">
        /// The instance preserved.
        /// </param>
        public override void Activate(bool instancePreserved)
        {
            var content = new ContentManager(this.ScreenManager.Game.Services, "Content");
            this.Song = content.Load<Song>(this.SongName);
        }

        /// <summary>
        /// The handle input.
        /// </summary>
        /// <param name="gameTime">
        /// The game time.
        /// </param>
        /// <param name="input">
        /// The input.
        /// </param>
        public override void HandleInput(GameTime gameTime, InputState input)
        {
            var escape = new InputAction(new[] { Keys.Escape }, true);
            if (escape.Evaluate(input))
            {
                return;
            }

            base.HandleInput(gameTime, input);
        }

        #endregion

        #region Methods

        /// <summary>
        /// When the user cancels the main menu, ask if they want to exit the sample.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="o">
        /// The o.
        /// </param>
        protected override void OnCancel(object sender, object o)
        {
            this.ScreenManager.Game.Exit();
        }

        /// <summary>
        /// The identities menu entry selected.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="o">
        /// The o.
        /// </param>
        private void IdentitiesMenuEntrySelected(object sender, object o)
        {
            this.ScreenManager.StopMusic();
            this.ScreenManager.AddScreen(new IdentitiesScreen());
        }

        /// <summary>
        /// The initiate load.
        /// </summary>
        /// Author: Mikkel Thordal Andersen
        private void InitiateLoad()
        {
            if (!Guide.IsVisible)
            {
                Client.Device = null;
                StorageDevice.BeginShowSelector(PlayerIndex.One, this.LoadFromDevice, null);
            }
        }

        /// <summary>
        /// The load from device.
        /// </summary>
        /// <param name="result">
        /// The result.
        /// </param>
        /// Author: Mikkel Thordal Andersen
        private void LoadFromDevice(IAsyncResult result)
        {
            Client.Device = StorageDevice.EndShowSelector(result);
            IAsyncResult r = Client.Device.BeginOpenContainer(Client.ContainerName, null, null);
            result.AsyncWaitHandle.WaitOne();
            StorageContainer container = Client.Device.EndOpenContainer(r);
            result.AsyncWaitHandle.Close();
            if (container.FileExists(Client.Filename))
            {
                Client.IsLoaded = true;
                Stream stream = container.OpenFile(Client.Filename, FileMode.Open);
                var formatter = new BinaryFormatter();
                var saveData = (SaveGame)formatter.Deserialize(stream);
                stream.Close();
                container.Dispose();

                Client.MainPlayer = saveData.Player;
                Client.MainPlayer.Animation.SpriteStrip = Client.Content.Load<Texture2D>(Client.MainPlayer.Image);

                Client.MainPlayer.InputState = new InputState();

                this.ScreenManager.StopMusic();
                this.ScreenManager.AddScreen(new GameplayScreen());

                foreach (Floor floor in saveData.Floors)
                {
                    if (floor.Visited)
                    {
                        floor.Background.LoadContent();
                    }

                    foreach (Enemy enemy in floor.Enemies)
                    {
                        enemy.Texture = Client.Content.Load<Texture2D>(enemy.Image);
                        enemy.Animation.SpriteStrip = enemy.Texture;
                        enemy.Blood.SpriteStrip = Client.Content.Load<Texture2D>("blood2");
                        enemy.DeathSound = Client.Content.Load<SoundEffect>(enemy.DeathSoundName);
                    }

                    foreach (ExtraObject extraObject in floor.ExtraObjects)
                    {
                        extraObject.Texture = Client.Content.Load<Texture2D>(extraObject.Image);
                        extraObject.Animation.SpriteStrip = extraObject.Texture;
                        extraObject.Sound = Client.Content.Load<SoundEffect>(extraObject.StringSound);
                    }

                    foreach (Player player in floor.Players)
                    {
                        player.ActiveWeapon.Texture = Client.Content.Load<Texture2D>(player.ActiveWeapon.Image);
                        player.ActiveWeapon.Animation.SpriteStrip =
                            Client.Content.Load<Texture2D>(player.ActiveWeapon.Image);
                        player.Texture = Client.Content.Load<Texture2D>(player.Image);
                        player.Animation.SpriteStrip = player.Texture;
                        player.InputState = new InputState();
                        player.ChangeWeaponSound = Client.Content.Load<SoundEffect>(Player.ChangeWeaponName);

                        foreach (Weapon weapon in player.Weapons)
                        {
                            weapon.Texture = Client.Content.Load<Texture2D>(weapon.Image);
                            weapon.Animation.SpriteStrip = Client.Content.Load<Texture2D>(weapon.Image);
                            weapon.Sound = Client.Content.Load<SoundEffect>(weapon.StringSound);
                        }
                    }

                    if (floor.Active)
                    {
                        floor.Players[0] = Client.MainPlayer;
                    }
                }

                if (Client.MainPlayer.Direction == MovementsEnum.Left)
                {
                    Client.MainPlayer.Animation.Flip(MovementsEnum.Left);
                }

                Client.Floors = saveData.Floors;
                Client.MainPlayer.ActiveWeapon.Sound =
                    Client.Content.Load<SoundEffect>(Client.MainPlayer.ActiveWeapon.StringSound);
                Client.MainPlayer.Blood.SpriteStrip = Client.Content.Load<Texture2D>("blood");
                Client.Elevator.NumberFloor = Client.Floors.Find(f => f.Active).Number;
                Client.Elevator.IsGoingToFloor = Client.Elevator.NumberFloor;
                Client.IsLoaded = false;
            }
        }

        /// <summary>
        /// The load game menu entry selected.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void LoadGameMenuEntrySelected(object sender, EventArgs e)
        {
            Client.Content = new ContentManager(this.ScreenManager.Game.Services, "Content");
            this.InitiateLoad();
        }

        /// <summary>
        /// Event handler for when the Play Game menu entry is selected.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="o">
        /// The o.
        /// </param>
        private void PlayGameMenuEntrySelected(object sender, object o)
        {
            // You can't start the game until you select a profile
            if (Client.MainPlayer == null)
            {
                return;
            }

            this.ScreenManager.StopMusic();
            this.ScreenManager.AddScreen(new GameplayScreen());
        }

        /// <summary>
        /// The statistics menu entry selected.
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="o">
        /// The o.
        /// </param>
        private void StatisticsMenuEntrySelected(object sender, object o)
        {
            this.ScreenManager.StopMusic();
            this.ScreenManager.AddScreen(new StatisticsScreen());
        }

        #endregion
    }
}